/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __ATC_AIRCRAFT_AGENT_HDR__
#define __ATC_AIRCRAFT_AGENT_HDR__


#include <qobject.h>
#include "atc_types.h"
#include "param.h"
#include <stdexcept>


namespace performance {
	
	//
	// performance::Performance
	//
	class Performance;

};


namespace atc {

	//
	// class declaration
	//

	struct AircraftData;
	class  AircraftHistory;
	class  AircraftPath;
	struct AircraftPathToken;
	class  AircraftPerformance;
	class  AircraftPlan;
	struct AircraftState;
	enum   ControlState;


	//
	// atc::aircraft_agent_error
	//

	struct aircraft_agent_error : public std::runtime_error{
		aircraft_agent_error(const std::string& msg)
			:std::runtime_error(msg) {}
	};

	//
	// atc::AircraftAgent
	//

	class AircraftAgent : public QObject {
		Q_OBJECT

	public:
		AircraftAgent( QObject * = 0, const char * = 0 );
		~AircraftAgent();

	public:
		void set_data( const AircraftData & );
		void set_path( const AircraftPath & );
		void set_launch( unsigned int );
		
		void 
		SetAcceptanceType(AircraftAcceptanceType a_type)
		{
			m_acceptanceType = a_type;
		}

	public:
		bool is_active() const { return _active; }
		bool is_vectoring() const { return _vectoring; }
		bool is_conflicted() const { return _conflicted; }
		
		AircraftAcceptanceType AcceptanceType() const
		{
			return m_acceptanceType;
		}

		void set_conflict() { set_conflict(true); }
		void clear_conflict(){ set_conflict(false); }

		void launch();
		void advance_position( int );

		void climb( int );
		
		void vector( double, double );
		void vector( double );
		void reroute( const AircraftPathToken *, Point );
		void require_level( int );

		//void update_position();
		bool collides_with( AircraftAgent *, double, double );

		void set_cfl( int );
		void set_velocity( int );
		void set_conflict( bool );

		void accept();
		void handoff();

		void set_control( ControlState );

		Point position( int = 0 );

		const char * callsign() const;
		const char * type    () const;
		double       calt    () const;
		double       speed   () const;

		double x() const;
		double y() const;
		double z() const;
		double a() const;

		double vel_min() const;
		double vel_std() const;
		double vel_max() const;

		double cfl_min() const;
		double cfl_std() const;
		double cfl_max() const;

		const AircraftPath    & path()    const { return *_path; }
		const AircraftHistory & history() const { return *_history; }

		ControlState control() const;

		void flag_missed_acceptance() { _missed_acceptance = true; }
		bool has_missed_acceptance() { return _missed_acceptance; }

	private slots:
		void activate();
		void deactivate();

	private:
		bool has_path();
		void initialize_state();
		void advance_state( int );
		void update_state();

		void record_event( KeyValues & );

	signals:
		void updated();
		void waypoint();

		void activated();
		void deactivated();

		void event_recorded( KeyValues & );

	private:
		unsigned int		 _launch;
		bool                 _active;

		double               _cfl;		// cleared flight level
		double               _vel;		// target velocity

		AircraftData        *_data;
	    AircraftPath		*_path;
		AircraftState       *_state;
		AircraftHistory     *_history;

		const performance::Performance *_performance;

		int    _overout_time;
		int    _handoff_time;
		bool   _vectoring;
		bool   _conflicted;
		bool   _require_level;
		double _tmp_throttle;

		bool			_missed_acceptance;
		AircraftAcceptanceType	m_acceptanceType;
	};

	//
	// 
	//
	typedef performance::Performance ACPerformance;

};


#endif
